// src/main.rs

#[allow(dead_code)]
#[allow(unused_variables)]
#[allow(unused_mut)]
#[allow(unused_assignments)]
fn main() {
    println!("Hello, world!");

    //1.变量和数据类型

    //不可变绑定
    let x: i32 = 1;
    //整型/浮点型 后缀
    let y: i32 = 13i32;
    let f: f64 = 1.3f64;

    //类型推断
    let implicit_x = 1;
    let implicit_f = 1.3;

    //算术运算
    let sum = x + y + 13;

    //可变变量
    let mut mutable = 1;
    mutable = 4;
    println!("sum is {}, mutable is {}", sum, mutable);
    mutable += 2;
    println!("mutable is {}", mutable);

    //字符串(Strings)
    //字符串字面量
    let x: &str = "Hello, world!";

    //输出
    println!("{} {}", f, x);

    //一个String,在堆上分配空间的字符串
    let s: String = "Hello, world!".to_string();

    //字符串分片
    let s_slice: &str = &s;

    println!("{} {}", s, s_slice);

    //数组(Vectors/arrays)
    //长度固定的数组(array)
    let four_ints: [i32; 4] = [1, 2, 3, 4];
    println!("{}", four_ints[2]);
    //动态数组(vector)
    let mut vec: Vec<i32> = vec![1, 2, 3, 4];
    vec.push(5);

    //分片(slices)
    let slice: &[i32] = &vec;

    //使用'{:?}'按调试样式输出
    println!("{:?} {:?}", vec, slice);

    //元组(tuples)

    //元组是固定大小的一组值,可以是不同的类型
    let x: (i32, &str, f64) = (1, "hello", 3.4);

    let (a, b, c) = x;
    println!("{} {} {}", a, b, c);

    //2.类型

    //结构体
    struct Point {
        x: i32,
        y: i32,
    }

    let origin: Point = Point { x: 0, y: 0 };
    println!("(Point= {}, {})", origin.x, origin.y);

    //匿名成员结构体，又叫“元组结构体”('tuple struct')
    struct Point2(i32, i32);

    let origin2: Point2 = Point2(0, 0);
    println!("(Point2= {}, {})", origin2.0, origin2.1);

    //基础的C风格枚举类型(enum)
    #[derive(Debug)] //让枚举类型可以用'{:?}'输出
    enum Direction {
        Left,
        Right,
        Up,
        Down,
    }

    let up = Direction::Up;
    println!("up is {:?}", up); //输出枚举成员的标识符

    //带数据的枚举类型
    #[derive(Debug)]
    enum OptionalI32 {
        AnI32(i32),
        Nothing,
    }

    let two: OptionalI32 = OptionalI32::AnI32(2);
    let nothing: OptionalI32 = OptionalI32::Nothing;
    println!("two is {:?}, nothing is {:?}", two, nothing);

    //泛型(Generics)
    struct Foo<T> {
        bar: T,
    }

    //这个在标准库中有类似的定义,叫做Option<T>
    enum Optional<T> {
        SomeVal(T),
        NoVal,
    }

    impl<T> Foo<T> {
        fn into_bar(self) -> T {
            self.bar
        }

        fn bar(&self) -> &T {
            &self.bar
        }

        fn bar_mut(&mut self) -> &mut T {
            &mut self.bar
        }
    }

    let a_foo: Foo<i32> = Foo { bar: 123 };
    println!("{}", a_foo.into_bar());

    //Traits(其他语言里面叫interface或typeclasses)
    trait Frobnicate<T> {
        fn frobnicate(self) -> Option<T>;
    }

    impl<T> Frobnicate<T> for Foo<T> {
        fn frobnicate(self) -> Option<T> {
            Some(self.bar)
        }
    }

    let another_foo = Foo { bar: 1 };
    println!("{:?}", another_foo.frobnicate()); //Some(1)

    //3.模式匹配(Pattern matching)

    let foo2: OptionalI32 = OptionalI32::AnI32(1);
    match foo2 {
        OptionalI32::AnI32(n) => println!("it's an i32:{}", n),
        OptionalI32::Nothing => println!("it's nothing"),
    }

    //高级模式匹配
    struct FooBar {
        x: i32,
        y: OptionalI32,
    }
    let bar = FooBar {
        x: 15,
        y: OptionalI32::AnI32(32),
    };

    match bar {
        FooBar {
            x: 0,
            y: OptionalI32::AnI32(0),
        } => println!("The numbers are both zero"),
        FooBar {
            x: n,
            y: OptionalI32::AnI32(m),
        } => {
            if n == m {
                println!("The numbers are the same");
            } else {
                println!("Different numbers: {} {}", n, m);
            }
        }
        FooBar {
            x: _,
            y: OptionalI32::Nothing,
        } => println!("The second number is Nothing!"),
    }

    //4.控制流(Control flow)

    //for循环
    let array = [1, 2, 3];
    for i in array {
        println!("for loop: {}", i);
    }

    //区间(ranges)
    for i in 0u32..10 {
        //0到9
        println!("range: {}", i);
    }

    let p = 3;
    //'if'
    if p == 1 {
        println!("Maths is working!");
    } else {
        println!("Oh no, maths is broken");
    }

    //if可以作为表达式使用
    let value = if true { "good" } else { "bad" };

    let mut p = 3;
    //while循环
    while p > 0 {
        p -= 1;
        println!("Hello World!");
    }

    //无限循环
    //loop {                    //该函数无法退出
    //    println!("looping forever");
    //}

    //5.内存安全和指针(Memory safety & pointers)

    //独占指针(Owned pointer)--同一时刻只能有一个对象能
    //拥有这个指针
    //意味着'Box'离开他的作用域后,内存会被自动释放
    let mut mine: Box<i32> = Box::new(3);
    *mine = 5;
    //now_its_mine获取了mine的所有权
    let mut now_its_mine: Box<i32> = mine;
    *now_its_mine += 2;
    println!("now_its_mine: {}", now_its_mine);
    //不能再使用mine,因为它的所有权已经被转移了
    //println!("mine: {}",mine); //编译错误

    //引用指针(Reference)--引用其他数据的不可变指针
    //当引用指向某个值,我们称为“借用”这个值
    //因为是不可变的借用,所以不能被修改,也不能移动
    //借用一直维持到生命周期结束,即离开作用域
    let mut var = 4;
    var = 3;
    let ref_var: &i32 = &var; //借用var

    println!("var is {}", var);
    println!("ref_var is {}", ref_var);
    //var = 5; //可以修改var
    // *ref_var = 6  //编译错误,不能通过不可变引用修改var

    // 可变引用 (Mutable reference)
    // 当一个变量被可变地借用时，也不可使用
    let mut var2 = 4;
    let ref_var2: &mut i32 = &mut var2;
    *ref_var2 += 2;

    println!("{}", *ref_var2); // 6
                               // var2 = 2; // 编译报错，因为 `var2` 被借用了
}

#[allow(dead_code)]
fn add_one(x: i32) -> i32 {
    x + 1
}

#[cfg(test)]
#[allow(unused_imports)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
